package com.atguigu.spzx.manager.service.impl;

import com.atguigu.spzx.common.exception.SpzxException;
import com.atguigu.spzx.common.interceptor.SpzxLoginAuthInterceptor;
import com.atguigu.spzx.manager.mapper.SysMenuMapper;
import com.atguigu.spzx.manager.service.SysMenuService;
import com.atguigu.spzx.model.entity.system.SysMenu;
import com.atguigu.spzx.model.entity.system.SysUser;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.system.SysMenuVo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Resource
    SysMenuMapper sysMenuMapper;
    @Override
    public List<SysMenu> listNestedMenus() {
        /*
            将sysmenu表拆成1级二级菜单表联查  不使用

            查询所有数据  在业务代码中将他们组装为父子菜单的集合
         */
        //查询所有菜单
        List<SysMenu> menus = sysMenuMapper.findAllMenus();
        //1、挑出1级菜单: parent_id = 0
        List<SysMenu> parents = menus.stream()
                //过滤parentId为0的数据
                .filter(menu -> menu.getParentId().longValue() == 0L)
                //将上面过滤出来的menu存到list集合中
                .collect(Collectors.toList());
        //2、挑出每个1级菜单的下一级设置给他
        buildMenuTree(menus, parents);
        //3、返回组装好的父菜单集合
        return parents;
    }
    //删除菜单业务
    @Override
    public void deleteById(Long id) {
        //判断删除的菜单是否有下一级菜单
        Integer count = sysMenuMapper.selectCountByPid(id);
        if(count.intValue()>0){
            //有下一级
            throw new SpzxException(ResultCodeEnum.NOT_EMPTY_ERROR,null);
        }
        //删除菜单
        sysMenuMapper.deleteById(id);

    }

    /**
     *
     * @param menus 所有的菜单
     * @param parents 父菜单集合
     */
    private void buildMenuTree(List<SysMenu> menus, List<SysMenu> parents) {
        //递归必须自己写递归结束条件
        if(CollectionUtils.isEmpty(parents)){
            // 如果传入的父菜单集合为空，表示它没有下一级了
            return;
        }
        parents.forEach(parent->{
            //如果menu的parent_id等于正在遍历的parent菜单的id  就是parent的子菜单
            List<SysMenu> children = menus.stream()
                    //过滤parentId为0的数据
                    .filter(menu -> menu.getParentId().longValue() == parent.getId().longValue())
                    //将上面过滤出来的menu存到list集合中
                    .collect(Collectors.toList());
            parent.setChildren(children);
            //对children进行遍历：如果他还有下一级继续设置
            buildMenuTree(menus , children);
        });
    }


    @Override
    public SysMenu getById(Long id) {
        return sysMenuMapper.findMenuById(id);
    }

    @Override
    public void update(SysMenu sysMenu) {
        sysMenuMapper.updateById(sysMenu);
    }

    @Override
    public void save(SysMenu sysMenu) {
        //如果menu的title和component属性值要求唯一，可以在代码中检查数据的唯一性（也可以再数据库中添加约束）
        sysMenuMapper.save(sysMenu);
    }

    @Override
    public List<SysMenuVo> listMyMenuTree() {
        //获取登录用户对象
        SysUser sysUser = SpzxLoginAuthInterceptor.THREAD_LOCAL.get();
        List<SysMenu> menus = sysMenuMapper.findMyMenusByUserId(sysUser.getId());
        //组装数据
        List<SysMenu> parents = menus.stream().filter(menu -> menu.getParentId().longValue() == 0l).collect(Collectors.toList());
        buildMenuTree(menus , parents);
        //将组装好的菜单数据每个菜单转为SysMenuVo对象
        List<SysMenuVo> sysMenuVos = parents.stream().map(parent -> {
            //将遍历的一级菜单转为sysMenuVo对象
            SysMenuVo sysMenuVo = new SysMenuVo();
            sysMenuVo.setTitle(parent.getTitle());
            sysMenuVo.setName(parent.getComponent());
            List<SysMenu> children = parent.getChildren();
            if (!CollectionUtils.isEmpty(children)) {
                //将一级菜单的二级菜单集合转为sysMenuVo对象的子集合
                List<SysMenuVo> sysMenuVoChildren = children.stream().map(child -> {
                    SysMenuVo childSysMenuVo = new SysMenuVo();
                    childSysMenuVo.setName(child.getComponent());
                    childSysMenuVo.setTitle(child.getTitle());
//                    childSysMenuVo.setChildren(null);
                    return childSysMenuVo;
                }).collect(Collectors.toList());

                sysMenuVo.setChildren(sysMenuVoChildren);
            }
            return sysMenuVo;
        }).collect(Collectors.toList());

        return sysMenuVos;
    }
}
